package com.train.mgr.modules.biz.utils;

import lombok.extern.slf4j.Slf4j;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.concurrent.TimeUnit;

@Slf4j
public class Mp4ToWavAdaptive {

    private static final int MAX_RETRY   = 2;          // 最多尝试次数
    private static final int TIMEOUT_SEC = 30;         // 单次超时（秒）

    public static boolean convert(File mp4, File wav) {
        for (int i = 0; i < MAX_RETRY; i++) {
            try {
                if (i > 0) log.warn("mp4→wav 第 {} 次重试", i);
                boolean ok = doConvert(mp4, wav);
                if (ok) return true;
                log.warn("第 {} 次转码失败，继续重试", i + 1);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                log.error("转码被中断，终止重试");
                return false;
            } catch (Exception e) {
                log.error("转码异常（第 {} 次）", i + 1, e);
            }
        }
        log.error("mp4→wav 已重试 {} 次，全部失败，终止", MAX_RETRY);
        return false;
    }

    /** 探测音频流：返回 {sampleRate, channels} */
    private static int[] probeAudio(File mp4) throws IOException {
        String[] cmd = {
                "ffprobe", "-v", "error", "-select_streams", "a:0",
                "-show_entries", "stream=sample_rate,channels",
                "-of", "csv=p=0", mp4.getAbsolutePath()
        };

        ProcessBuilder pb = new ProcessBuilder(cmd);
        pb.redirectErrorStream(true);
        Process p = pb.start();

        String line;
        try (BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()))) {
            line = br.readLine();  // 示例：44100,2
        }

        if (line == null || line.trim().isEmpty()) {
            throw new IOException("无法读取音频流信息，请确认文件包含音频轨道");
        }

        String[] parts = line.trim().split(",");
        if (parts.length != 2) {
            throw new IOException("ffprobe 输出格式异常：" + line);
        }

        int sampleRate = Integer.parseInt(parts[0]);
        int channels = Integer.parseInt(parts[1]);
        return new int[]{sampleRate, channels};
    }

    /** 根据实际属性决定目标参数 */
    private static int decideTargetRate(int originalRate) {
        return originalRate >= 16000 ? 16000 : 8000;
    }

    /** 真正转码 */
    public static boolean convertOld(File mp4, File wav) {
        try {
            int[] info = probeAudio(mp4);
            int srcRate = info[0];
            int srcCh = info[1];
            int tgtRate = decideTargetRate(srcRate);

            String[] cmd = {
                    "ffmpeg", "-y",
                    "-i", mp4.getAbsolutePath(),
                    "-vn",
                    "-acodec", "pcm_s16le",
                    "-ar", String.valueOf(tgtRate),
                    "-ac", "1",
                    wav.getAbsolutePath()
            };

            ProcessBuilder pb = new ProcessBuilder(cmd);
            pb.redirectErrorStream(true);
            Process p = pb.start();

            try (BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()))) {
                String l;
                while ((l = br.readLine()) != null) {
                    // 静默处理，也可以写日志
                }
            }
            return p.waitFor() == 0;
        } catch (Exception e) {
            Thread.currentThread().interrupt();
            return false;
        }
    }

    /** 真正执行一次转码（带超时） */
    private static boolean doConvert(File mp4, File wav) throws InterruptedException,IOException {
        int[] info = probeAudio(mp4);
        int srcRate = info[0];
        int tgtRate = decideTargetRate(srcRate);

        String[] cmd = {
                "ffmpeg", "-y",
                "-i", mp4.getAbsolutePath(),
                "-vn", "-acodec", "pcm_s16le",
                "-ar", String.valueOf(tgtRate),
                "-ac", "1",
                wav.getAbsolutePath()
        };

        ProcessBuilder pb = new ProcessBuilder(cmd);
        pb.redirectErrorStream(true);
        Process p = pb.start();

        // 消费 stdout，避免缓冲区满
        try (BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()))) {
            String line;
            while ((line = br.readLine()) != null) {
                // 如需调试：log.debug("[ffmpeg] {}", line);
            }
        }

        // 等待进程结束（带超时）
        boolean finished = p.waitFor(TIMEOUT_SEC, TimeUnit.SECONDS);
        if (!finished) {
            log.error("ffmpeg 超时（>{}秒），强制销毁", TIMEOUT_SEC);
            p.destroyForcibly();
            return false;
        }
        return p.exitValue() == 0;
    }

    /* ---------------- 测试 ---------------- */
//    public static void main(String[] args) throws IOException {
//        if (args.length < 2) {
//            System.out.println("用法: java Mp4ToWavAdaptive <in.mp4> <out.wav>");
//            System.exit(1);
//        }
//
//        long t = System.currentTimeMillis();
//        boolean ok = convert(new File(args[0]), new File(args[1]));
//        long cost = System.currentTimeMillis() - t;
//
//        System.out.println(ok ? "转换成功" : "转换失败");
//        System.out.printf("耗时: %.2f s%n", cost / 1000.0);
//    }

}